/**
 * 控制选区样式
 */

import Rte from 'editor/index'
import { InterimSets } from 'share/declare'
import { clearInterimCssRule, deleteInterimCssRules, interimSetsToString, setInterimCssRuleByRuleString } from 'share/interim'

export default class RteSelection {
  private selectionchange: Function

  /**
   * 用于实现选区效果的 css selectorText 集合
   */
  private selectorText: Map<string, Set<string>> = new Map()

  /**
   * 行内元素的选中样式
   */
  public inlineCSSContent: string = ''

  /**
   * 块儿元素的选中样式
   */
  public blockCSSContent: string = ''

  /**
   * 空行元素的选中样式
   */
  public emptyrowCSSContent: string = ''

  /**
   * 文档编辑区跟节点的 id attribute
   */
  public get id() {
    return this.editor.$data.id
  }

  /**
   * 用于进行 css rule 操作的 <style>
   */
  public get interim() {
    return this.editor.$refs.selection
  }

  public constructor(public editor: Rte) {
    // 文本选中样式
    editor.$data.$depend(
      ['selectTextColor', 'selectBackground'],
      () => {
        const rules: InterimSets = [
          ['position', 'relative'],
          ['color', editor.$data.selectTextColor],
          ['background-color', editor.$data.selectBackground],
        ]
        this.inlineCSSContent = interimSetsToString(rules)
      },
      true
    )

    // 块儿与空行选中样式的公共部分
    const common: InterimSets = [
      ['content', "''"],
      ['display', 'inline-block'],
      ['height', '100%'],
      ['position', 'absolute'],
      ['top', 0],
      ['left', 0],
    ]

    // 块儿选中样式
    editor.$data.$depend(
      ['selectBackground', 'selectZIndex'],
      () => {
        const ruleContent: InterimSets = [
          ['width', '100%'],
          ['background-color', editor.$data.selectBackground],
          ['z-index', editor.$data.selectZIndex],
          ...common,
        ]
        this.blockCSSContent = interimSetsToString(ruleContent)
      },
      true
    )

    // 空行选中样式
    editor.$data.$depend(
      ['selectEmptyWidth', 'selectBackground', 'selectZIndex'],
      () => {
        const ruleContent: InterimSets = [
          ['width', editor.$data.selectEmptyWidth],
          ['background-color', editor.$data.selectBackground],
          ['z-index', editor.$data.selectZIndex],
          ...common,
        ]
        this.emptyrowCSSContent = interimSetsToString(ruleContent)
      },
      true
    )

    // selectionchange callback
    this.selectionchange = () => {
      // if (editor.mouse.mousezone.mousedown === ZONE.EDITABLE) {
      //   // 清除选区样式
      //   this.clear()
      //   const ranges = editor.range.get(true)
      //   if (ranges?.length) {
      //     // 设置选区样式
      //     ranges.forEach((row) => {
      //       switch (row.type) {
      //         case RangeType.EMPTYROW:
      //           ranges.length > 1 && this.selectEMPTYROWRow(row.roffset + 1)
      //           break
      //         case RangeType.INLINEROW:
      //           this.selectInlineRow(row.roffset + 1, row.soffset + 1, row.eoffset + 1)
      //           break
      //       }
      //     })
      //   }
      // }
    }
  }

  public bindListener() {
    // @ts-ignore
    document.addEventListener('selectionchange', this.selectionchange)
    return this
  }

  public unbindListener() {
    // @ts-ignore
    document.removeEventListener('selectionchange', this.selectionchange)
    return this
  }

  public getLineId(line: number | string) {
    if (typeof line === 'number') {
      return this.editor.content.lineId[line]
    }
    return line
  }

  /**
   * 设置选区（inline行）
   * @param line string：选区的行 ID。number：选区的行号，从 1 开始。
   * @param start 选区开始的列号，从 1 开始
   * @param end 选区结束的列号
   */
  public selectInlineRow(line: string | number, start: number, end: number) {
    const lineId = this.getLineId(line)

    // 被选中的行内元素
    const textColorSelector = `#${lineId} > :nth-child(n+${start}):nth-child(-n+${end})`
    setInterimCssRuleByRuleString(this.interim, textColorSelector, this.inlineCSSContent)

    // 被选中的块儿元素
    const bgColorSelector = `${textColorSelector}[${this.editor.$data.blockLabel}]::after`
    setInterimCssRuleByRuleString(this.interim, bgColorSelector, this.blockCSSContent)

    this.selectorText.set(lineId, new Set([textColorSelector, bgColorSelector]))
    return this
  }

  /**
   * 设置选区（空行）
   * @param line string：选区的行 ID。number：选区的行号，从 1 开始。
   */
  public selectEMPTYROWRow(line: string | number) {
    const lineId = this.getLineId(line)

    const lineSelectorText = `#${lineId}`
    setInterimCssRuleByRuleString(this.interim, lineSelectorText, `position: relative;`)

    const selectorText = `${lineSelectorText}::after`
    setInterimCssRuleByRuleString(this.interim, selectorText, this.emptyrowCSSContent)

    this.selectorText.set(lineId, new Set([lineSelectorText, selectorText]))
    return this
  }

  /**
   * 设置选区（普通的）
   * @param line string：选区的行 ID。number：选区的行号，从 1 开始。
   * @param start 选区开始的列号，从 1 开始
   * @param end 选区结束的列号
   */
  public select(line: number): void
  public select(line: number, start: number, end: number): void
  public select(line: number, start?: number, end?: number) {
    // const { editable } = this.editor.$refs
    // const elem = editable.children[line - 1]

    // // 判断该行的选区类型
    // const type = emptyrowRow(editable, elem) ? RangeType.EMPTYROW : RangeType.INLINEROW
    // switch (type) {
    //   case RangeType.EMPTYROW:
    //     this.selectEMPTYROWRow(line)
    //     break
    //   case RangeType.INLINEROW:
    //     this.selectInlineRow(line, start as number, end as number)
    //     break
    // }
    return this
  }

  /**
   * 清除选区
   */
  public clear(line?: number | string) {
    if (typeof line === 'number' || typeof line === 'string') {
      const lineId = this.getLineId(line)
      const lineSelectorText = this.selectorText.get(lineId)
      if (lineSelectorText && lineSelectorText.size) {
        deleteInterimCssRules(this.interim, [...lineSelectorText])
        this.selectorText.delete(lineId)
      }
    } else {
      clearInterimCssRule(this.interim)
      this.selectorText.clear()
    }
    return this
  }
}
